package tk.mybatis.springboot.ping.service.impl;

import java.io.BufferedReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.pingplusplus.model.Charge;
import com.pingplusplus.model.Event;
import com.pingplusplus.model.Webhooks;

import tk.mybatis.mapper.util.StringUtil;
import tk.mybatis.springboot.mapper.InsuranceOrderMapper;
import tk.mybatis.springboot.mapper.OpenOrderMapper;
import tk.mybatis.springboot.mapper.TCouponsMapper;
import tk.mybatis.springboot.mapper.TOpenOrderKernelMapper;
import tk.mybatis.springboot.mapper.TOrderCouponMapMapper;
import tk.mybatis.springboot.mapper.TUsersCouponMapper;
import tk.mybatis.springboot.model.InsuranceOrder;
import tk.mybatis.springboot.model.Message;
import tk.mybatis.springboot.model.OpenOrder;
import tk.mybatis.springboot.model.TCoupons;
import tk.mybatis.springboot.model.TOpenOrderKernel;
import tk.mybatis.springboot.model.TOrderCouponMap;
import tk.mybatis.springboot.model.TUsersCoupon;
import tk.mybatis.springboot.ping.Ping;
import tk.mybatis.springboot.ping.WebhooksVerifyExample;
import tk.mybatis.springboot.ping.service.PingService;
import tk.mybatis.springboot.share.util.OpenOrderStatus;
import tk.mybatis.springboot.share.util.PrintObj;


@Service
@Transactional
public class PingServiceImpl implements PingService{
	@Autowired
	private TUsersCouponMapper tUsersCouponMapper;

	@Autowired
	private TCouponsMapper tCouponsMapper;

	@Autowired
	private InsuranceOrderMapper insuranceOrderMapper;

	@Autowired
	private TOrderCouponMapMapper orderCouponMapMapper;
	
	@Autowired
	private OpenOrderMapper openOrderMapper;
	
	@Autowired
	private TOpenOrderKernelMapper tOpenOrderKernelMapper;

	private static Logger LOGGER = LogManager.getLogger(PingServiceImpl.class);

	@Override
	public void web(String signature, HttpServletRequest request) throws Exception {
		request.setCharacterEncoding("UTF8");
		// 获得 http body 内容
		BufferedReader reader = request.getReader();
		StringBuffer buffer = new StringBuffer();
		String string;
		while ((string = reader.readLine()) != null) {
			buffer.append(string);
		}
		reader.close();
		Event event = Webhooks.eventParse(buffer.toString());
		if (!WebhooksVerifyExample.runDemos(buffer.toString(), signature)) {
			return;
		}
		Charge charge = (Charge) event.getData().getObject();
		if ("charge.succeeded".equals(event.getType())) {
			List<InsuranceOrder> data = insuranceOrderMapper.getByReturnServiceNo(charge.getOrderNo());
			if(data !=null && data.size() > 0){
				InsuranceOrder order = new InsuranceOrder();
				for(InsuranceOrder insuranceOrder: data){
					if(1 ==insuranceOrder.getStatus()){
						order = insuranceOrder;
						break;
					}
				}
				order.setReturnServiceNo(charge.getOrderNo());
				order.setStatus(2);
				List<TOrderCouponMap> tOrderCouponMaps = orderCouponMapMapper.selectByOrder(order.getId());
				for (TOrderCouponMap tOrderCouponMap : tOrderCouponMaps) {
					tUsersCouponMapper.usedById(Integer.valueOf(tOrderCouponMap.getCouponId()));
				}
				OpenOrder byServiceNo = openOrderMapper.getByServiceNoAndStatus(charge.getOrderNo(),
						OpenOrderStatus.ResuranceSuccess);
				byServiceNo.setStatus(2);
				openOrderMapper.update(byServiceNo);
				insuranceOrderMapper.update(order);

				LOGGER.info("pingpp pay success="+charge.getOrderNo());
			}
		}

	}

	@Override
	public Message pay(String id, HttpServletRequest request, Integer type, String url, Integer usersCouponId) throws Exception {
		String ip = request.getRemoteAddr();
		String sub = "支付";
		String channel = "alipay";
		List<InsuranceOrder> data = insuranceOrderMapper.getByReturnServiceNo(id);
		InsuranceOrder order = new InsuranceOrder();
		BigDecimal money;
		for(InsuranceOrder insuranceOrder: data){
			if(1 ==insuranceOrder.getStatus()){
				order = insuranceOrder;
				break;
			}
		}
		TOpenOrderKernel tOpenOrderKernel = new TOpenOrderKernel();
		tOpenOrderKernel.setServiceno(id);
		List<TOpenOrderKernel> select = tOpenOrderKernelMapper.select(tOpenOrderKernel);
		tOpenOrderKernel = select.get(0);
		money = new BigDecimal(tOpenOrderKernel.getTotalcost()).subtract(StringUtil.isEmpty(tOpenOrderKernel.getRebates()) ? BigDecimal.ZERO : new BigDecimal(tOpenOrderKernel.getRebates()));
		if(usersCouponId != null){
			TUsersCoupon tUsersCoupon = tUsersCouponMapper.findByid(usersCouponId);
			if(1 == tUsersCoupon.getIsenabled()){
				return Message.error("该优惠券已被使用");
			}else if(2 == tUsersCoupon.getIsenabled()){
				return Message.error("该优惠券已过期");
			}
			TCoupons tCoupons = tCouponsMapper.findByid(tUsersCoupon.getCouponid());
			if(tCoupons.getDicount_way() == 1){
				money = money.subtract(money.multiply(new BigDecimal(tCoupons.getDiscountRate())).divide(new BigDecimal(100)));
			}else{
				money = money.subtract(new BigDecimal(tCoupons.getDiscountRate()));
			}
			TOrderCouponMap orderCouponMap = new TOrderCouponMap();
			orderCouponMap.setOrderId(order.getId().toString());
			orderCouponMapMapper.delete(orderCouponMap);
			orderCouponMap.setCouponId(String.valueOf(usersCouponId));
			orderCouponMapMapper.insertSelective(orderCouponMap);

		}

		Map<String, Object> chargeParams = new HashMap<String, Object>();
		switch (type) {
			case 1:
				channel = "alipay";
				break;
			case 2:
				channel = "alipay_wap";
				Map<String, String> extramap = new HashMap<String, String>();
				extramap.put("success_url", url);
				chargeParams.put("extra", extramap);
				break;
			case 3:
				channel = "alipay_qr";
				break;
			case 4:
				channel = "alipay_pc_direct";
				break;
			case 5:
				channel = "wx";
				break;
			case 6:
				channel = "wx_pub";
				break;
			case 7:
				channel = "wx_pub_qr";
				break;
			case 8:
				channel = "wx_wap";
				break;
		}
		Charge charge = Ping.pay(money.multiply(new BigDecimal(100)).intValue(), id, ip, channel,
				chargeParams, sub);

		LOGGER.info("Charge="+PrintObj.typeToString("Charge", charge));
		return Message.success(charge);
	}

}
